package com.digua.base.socket.dispatcher

import android.os.Process
import com.digua.base.socket.dispatcher.ResponseProcessEngine.EngineEntity
import com.digua.base.util.LogUtil
import java.util.concurrent.ArrayBlockingQueue
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

class EngineThread : Thread() {
    private val jobQueue = ArrayBlockingQueue<EngineEntity>(10)
    private var executorService: ExecutorService? = null
    private var stop = false

    @Synchronized
    override fun start() {
        stop = false
        super.start()
    }

    override fun run() {
        super.run()
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)
        while (!stop) {
            try {
                val entity = jobQueue.take()
                if (entity.isError) {
                    entity.dispatcher?.onSendDataError(entity.errorResponse, entity.delivery)
                } else {
                    entity.response?.onResponse(entity.dispatcher, entity.delivery)
                }
                EngineEntity.release(entity)
            } catch (e: InterruptedException) {
                if (stop) return
            } catch (e: Exception) {
                LogUtil.e("run()->Exception", e)
            }
        }
    }

    fun add(entity: EngineEntity) {
        if (!jobQueue.offer(entity)) {
            LogUtil.e("Offer response to Engine failed!start an thread to put.")
            if (executorService == null) executorService = Executors.newCachedThreadPool()
            executorService?.execute(Runnable {
                if (stop) return@Runnable
                try {
                    jobQueue.put(entity)
                } catch (e: Exception) {
                    if (stop) {
                        LogUtil.e("put response failed!", e)
                    } else {
                        interrupt()
                    }
                }
            })
        }
    }

    /**
     * 结束线程
     */
    fun quit() {
        stop = true
        jobQueue.clear()
        interrupt()
    }
}